package com.jmz.apt.api.service;

import com.alibaba.fastjson.JSON;
import com.jmz.apt.api.dao.AdminRoleDao;
import com.jmz.apt.api.dto.impl.AdminResourceDto;
import com.jmz.apt.api.dto.impl.AdminRoleDto;
import com.jmz.apt.api.dto.impl.AdminUserDto;
import com.jmz.apt.api.entity.dbEntity.*;
import com.jmz.apt.api.enums.CurrencyCode;
import com.jmz.apt.api.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description : {   }
 * @Author : create by NanFeng on 2019-11-06 14:53
 */
@Transactional
@Service
public class AdminRoleService {

    @Autowired
    private AdminRoleDao roleDao;

    @Autowired
    private MenuService menuService;


    /**
     * 查询所有角色
     *
     * @return
     */
    public List<JmzAdminRole> getRoles() {
        return roleDao.getRoles();
    }

    /**
     * 删除角色
     *
     * @param ids
     * @return
     */
    public boolean deleteRole(List<Integer> ids) {
        boolean flag = false;
        try {
            //删除用户角色关系表
            boolean deleteUserRole = roleDao.deleteUserRole(ids) > 0;
            //删除资源角色关系表
            boolean deleteResourceRole = roleDao.deleteResourceRole(ids) > 0;
            //删除角色
            boolean deleteRole = roleDao.deleteRole(ids) > 0;

            if (deleteUserRole && deleteResourceRole && deleteRole)
                flag = true;
            else
                flag = false;
        } catch (Exception e) {
            throw new BusinessException("0", "保存失败");
        }

        return flag;
    }

    /**
     * 保存角色、保存用户角色、保存角色权限
     *
     * @param lists
     * @return
     */
    public boolean saveRole(List<List<AdminRoleDto>> lists) {
        boolean flag = false;
        if (!CollectionUtils.isEmpty(lists)) {
            List<AdminRoleDto> list = lists.get(0);
            if (!CollectionUtils.isEmpty(list)) {
                AdminRoleDto roleDto = list.get(0);
                if (null != roleDto) {
                    try {
                        // 保存角色返回主键ID
                        Integer roleId = saveRoleDetail(roleDto);
                        if (roleId == CurrencyCode.ERROR_CODE.getValue()) {
                            return flag;
                        }

                        // 保存用户角色
                        List<Integer> userIds = getUserIds(roleDto.getUsers());
                        boolean insertUserRoleBatch = roleDao.insertUserRoleBatch(userIds, roleId) > 0;

                        // 保存角色资源
                        List<Integer> resourceIds = getResourceIds(roleDto.getResources());
                        boolean insertResourceRoleBatch = roleDao.insertResourceRoleBatch(resourceIds, roleId) > 0;

                        if (null != roleId && insertUserRoleBatch && insertResourceRoleBatch)
                            flag = true;
                        else
                            flag = false;
                    } catch (Exception e) {
                        throw new BusinessException("0", "保存失败");
                    }
                } else {
                    flag = false;
                }
            } else {
                flag = false;
            }
        } else {
            flag = false;
        }
        return flag;
    }

    /**
     * 保存或修改角色
     *
     * @param roleDto
     * @return
     */
    public Integer saveRoleDetail(AdminRoleDto roleDto) {
        Integer id = null;
        // 新增
        if (null == roleDto.getId()) {
            // 判断当前角色名称是否已被使用
            JmzAdminRole one = roleDao.findOneByRole(roleDto);
            if (null != one) {
                id = CurrencyCode.ERROR_CODE.getValue();
            } else {
                roleDao.saveRole(roleDto);
                id = roleDto.getId();
            }
        } else {
            // 更新
            JmzAdminRole one = roleDao.findOneNotOwnId(roleDto);
            if (null != one) {
                id = CurrencyCode.ERROR_CODE.getValue();
            } else {
                roleDao.updateRole(roleDto);
                id = roleDto.getId();
            }
        }
        return id;
    }

    /**
     * 获取用户id
     *
     * @param users
     * @return
     */
    private List<Integer> getUserIds(List<JmzAdminUser> users) {
        List<Integer> userIds = new ArrayList<>();
        users.forEach(user -> userIds.add(user.getId()));
        return userIds;
    }

    /**
     * 获取资源id
     *
     * @param resources
     * @return
     */
    private List<Integer> getResourceIds(List<JmzAdminResource> resources) {
        List<Integer> resourceIds = new ArrayList<>();
        resources.forEach(resource -> resourceIds.add(resource.getId()));
        return resourceIds;
    }


    /**
     * @param lists
     * @return Map :{role:jmz_admin_role对象，}
     */
    public Map getInfoByRole(List<List<AdminRoleDto>> lists) {
        Map<String, Object> map = new HashMap<>();

        if (!CollectionUtils.isEmpty(lists)) {
            List<AdminRoleDto> list = lists.get(0);
            if (!CollectionUtils.isEmpty(list)) {
                AdminRoleDto roleDto = list.get(0);
                Integer roleId = roleDto.getId();
                if (null != roleId) {
                    // 获取role详情
                    JmzAdminRole role = roleDao.findOneByRole(roleDto);
                    map.put("roleDetail", JSON.toJSON(role));

                    // 获取该角色已选中的用户
                    List userDetail = this.getUsers(roleId);
                    map.put("userDetail", userDetail);

                    // 获取该角色已选中的资源
                    List resourceDetail = this.getResources(roleId);
                    map.put("resourceDetail", resourceDetail);
                } else {
                    throw new BusinessException("0", "roleId不可为空");
                }
            } else {
                throw new BusinessException("0", "传入参数不可为空");
            }
        } else {
            throw new BusinessException("0", "传入参数不可为空");
        }
        return map;
    }

    /**
     * 用于回显角色绑定资源,checked =1 为选中状态
     * //TODO 该方法很low，有时间优化
     *
     * @param roleId
     * @return
     */
    private List<AdminResourceDto> getResources(Integer roleId) {
        List<AdminResourceDto> list = menuService.getList();
        for (AdminResourceDto dto : list) {
            JmzAdminRoleResource roleResource = roleDao.selectOneByResourceIdAndRoleId(roleId, dto.getId());
            if (null != roleResource)
                dto.setChecked(CurrencyCode.CHECKED_CODE.getValue());
            else
                dto.setChecked(CurrencyCode.UNCHECKED_CODE.getValue());

        }
        // 封装树形结构
        List<AdminResourceDto> resourceDtos = menuService.encapsulationMenus(list);
        return resourceDtos;
    }

    /**
     * 用于回显角色绑定用户,checked =1 为选中状态
     *
     * @param roleId
     * @return
     */
    private List<AdminUserDto> getUsers(Integer roleId) {
        List<AdminUserDto> userDto = roleDao.selectUsers();
        for (AdminUserDto dto : userDto) {
            // 判断该用户和该角色是否在中间表，如果在，该用户的checked标识为勾选状态
            JmzAdminUserRoles userRole = roleDao.selectOneByUserIdAndRoleId(roleId, dto.getId());
            if (null != userRole)
                dto.setChecked(CurrencyCode.CHECKED_CODE.getValue());
            else
                dto.setChecked(CurrencyCode.UNCHECKED_CODE.getValue());

        }
        return userDto;
    }


    /**
     * 修改角色相关
     *
     * @param lists
     * @return
     */
    public boolean updateRole(List<List<AdminRoleDto>> lists) {
        boolean flag = false;
        if (!CollectionUtils.isEmpty(lists)) {
            List<AdminRoleDto> list = lists.get(0);
            if (!CollectionUtils.isEmpty(list)) {
                AdminRoleDto roleDto = list.get(0);
                if (null != roleDto) {
                    // 获取角色id
                    Integer roleId = roleDto.getId();
                    if (null != roleId) {
                        // 更新角色
                        Integer one = saveRoleDetail(roleDto);
                        if (one == CurrencyCode.ERROR_CODE.getValue()) {
                            return flag;
                        }
                        // 修改角色用户
                        boolean flag1 = updateRoleUser(roleId, roleDto);
                        // 修改角色资源
                        boolean flag2 = updateRoleResource(roleId, roleDto);

                        if (flag1 && flag2)
                            flag = true;
                        else
                            flag = false;
                    } else {
                        throw new BusinessException("0", "roleId不可为空");
                    }
                } else {
                    flag = false;
                }
            } else {
                flag = false;
            }
        } else {
            flag = false;
        }
        return flag;
    }

    private boolean updateRoleResource(Integer roleId, AdminRoleDto roleDto) {
        boolean flag;
        // 更新绑定的资源  逻辑是先删除再保存
        List<Integer> deleteIds = new ArrayList<>();
        deleteIds.add(roleId);
        // 删除
        boolean flag1 = roleDao.deleteResourceRole(deleteIds) > 0;

        List<Integer> insertIds = new ArrayList();
        List<JmzAdminResource> resources = roleDto.getResources();
        resources.forEach(resource -> insertIds.add(resource.getId()));
        // 新增
        boolean flag2 = roleDao.insertResourceRoleBatch(insertIds, roleId) > 0;

        if (flag1 && flag2)
            flag = true;
        else
            flag = false;
        return flag;
    }

    private boolean updateRoleUser(Integer roleId, AdminRoleDto roleDto) {
        boolean flag;
        // 更新绑定的用户  逻辑是先删除再保存
        List<Integer> deleteIds = new ArrayList<>();
        deleteIds.add(roleId);
        // 删除
        boolean flag1 = roleDao.deleteUserRole(deleteIds) > 0;

        List<Integer> insertIds = new ArrayList();
        List<JmzAdminUser> usersIds = roleDto.getUsers();
        usersIds.forEach(user -> insertIds.add(user.getId()));
        // 新增
        boolean flag2 = roleDao.insertUserRoleBatch(insertIds, roleId) > 0;

        if (flag1 && flag2)
            flag = true;
        else
            flag = false;
        return flag;
    }
}
